package com.yeyks.commonReference.append.pay;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.yeyks.common.em.pay.PayAttach;
import com.yeyks.common.em.pay.PayTypeEnum;
import com.yeyks.common.em.vip.VipCardTypeEnum;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.utils.ArgumentsCheckUtil;
import com.yeyks.commonReference.append.alipay.config.AlipayAppProperties;
import com.yeyks.commonReference.append.alipay.service.AlipayService;
import com.yeyks.commonReference.append.wxPay.config.WeChatYyksBaseProperties;
import com.yeyks.commonReference.append.wxPay.dto.WxPayParam;
import com.yeyks.commonReference.append.wxPay.service.WeiXinPayService;
import com.yeyks.commonReference.service.order.OrderHeadService;
import com.yeyks.commonReference.service.order.OrderPayRecordService;
import com.yeyks.commonReference.service.vip.MemberCardEnableOrderService;
import com.yeyks.commonReference.service.consumer.UserMemberCardService;
import com.yeyks.order.dal.domain.OrderHead;
import com.yeyks.vip.dal.domain.MemberCardEnableOrder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/*
支付统一接口
 */
@Slf4j
@Service
public class PayService {

    @Autowired
    private PayService payService;
    @Autowired
    private OrderHeadService orderHeadService;
    @Autowired
    private AlipayService alipayService;
    @Autowired
    private AlipayAppProperties alipayAppProperties;
    @Autowired
    private WeiXinPayService weiXinPayService;
    @Autowired
    private WeChatYyksBaseProperties wxProperties;
    @Autowired
    private UserMemberCardService userMemberCardService;
    @Autowired
    private OrderPayRecordService orderPayRecordService;
    @Autowired
    private MemberCardEnableOrderService memberCardEnableOrderService;

    //订单调用支付
    public Map<String, Object> orderHeadPay(String payType, String orderNo, String wxOpenId, String payPassword, String ip) {
        OrderHead orderHead = orderHeadService.getOne(new QueryWrapper<OrderHead>().eq(OrderHead.ORDER_NO, orderNo));
        if (Objects.isNull(orderHead)) {
            throw new ServiceException("订单不存在");
        }
        Integer snapshotTotalFee = orderHead.getSnapshotTotalFee();
        Map<String, Object> map = new HashMap<>();
        map.put("orderId", orderHead.getId());
        if (doPay(map, PayAttach.ORDER_PAY.desc(), payType, orderNo, snapshotTotalFee, wxOpenId, ip, payPassword, orderHead.getUserId())) {
            return map;
        }
        return null;
    }

    //卡激活enable的调用支付(线下) v3.4.a
    public Map<String, Object> memberCardEnableorderPay(String payType, String orderNo, String wxOpenId, String ip) {
        return memberCardEnableorderPay(payType,orderNo,wxOpenId,ip,PayAttach.MEMBER_CARD_ENABLE_ORDER.desc());
    }

    //卡激活enable的调用支付(线上) v3.8.3
    public Map<String, Object> memberCardEnableorderPayOnline(String payType, String orderNo, String wxOpenId, String ip) {
        return memberCardEnableorderPay(payType,orderNo,wxOpenId,ip,PayAttach.MEMBER_CARD_ENABLE_ORDER_ONLINE.desc());
    }

    //卡激活enable的调用支付 v3.8.3
    public Map<String, Object> memberCardEnableorderPay(String payType, String orderNo, String wxOpenId, String ip,String payAttachDesc) {
        MemberCardEnableOrder memberCardEnableOrder = memberCardEnableOrderService.getOne(new QueryWrapper<MemberCardEnableOrder>().eq(MemberCardEnableOrder.ORDER_NO, orderNo));
        if (Objects.isNull(memberCardEnableOrder)) {
            throw new ServiceException("订单不存在");
        }
        Integer payValue = memberCardEnableOrder.getPayValue();
        Map<String, Object> map = new HashMap<>();
        map.put("orderId", memberCardEnableOrder.getId());
        if (doPay(map, payAttachDesc, payType, orderNo, payValue, wxOpenId, ip, null, null)) {
            return map;
        }
        return null;
    }

    /**
     * 支付统一调用的方法
     *
     * @param resultMap     用于返回的map对象
     * @param orderType     订单类型
     * @param payType       支付类型
     * @param orderNo       订单号
     * @param paymentAmount 支付金额
     * @param wxOpenId      微信openid
     * @param ip            用户ip
     * @param payPassword   钱包的支付密码
     * @param userId        用户id
     * @return
     */
    public boolean doPay(Map<String, Object> resultMap, String orderType, String payType, String orderNo, Integer paymentAmount, String wxOpenId, String ip, String payPassword, Integer userId) {
        try {
            HashMap<String, String> attachMap = new HashMap<>();
            //订单类型
            attachMap.put("orderType", orderType);
            //支付类型
            attachMap.put("payType", payType);
            //支付宝APP
            if (PayTypeEnum.ALIPAY.desc().equals(payType)) {
                String payInfo = alipayService.unifiedPay(orderNo, paymentAmount, alipayAppProperties.getNewNotifyUrl(), JSONUtil.toJsonStr(attachMap));
                resultMap.put("payInfo", payInfo);
                return true;
            }
            //微信APP
            else if (PayTypeEnum.WXPAY.desc().equals(payType)) {
                WxPayParam wxPayParam = getWxPayParam(orderType, payType, orderNo, paymentAmount, wxOpenId, "APP", ip, attachMap);
                Map<String, String> wxMap = weiXinPayService.appDisposePay(wxPayParam);
                String payInfo = JSONObject.toJSONString(wxMap);
                resultMap.put("payInfo", payInfo);
                return true;
            }
            //jsapi
            else if (PayTypeEnum.GZH.desc().equals(payType) || PayTypeEnum.XCX.desc().equals(payType)) {
                if (ArgumentsCheckUtil.strIsNull(wxOpenId)) {
                    throw new ServiceException("openId必传");
                }
                //小程序和公众号用的是同一个商户订单号体系,商户订单号不能重复,故同一修改订单号,添加后缀xcx
                String orderNoNew = orderNo;
                if (PayTypeEnum.XCX.desc().equals(payType)) {
                    orderNoNew += PayTypeEnum.XCX.desc();
                }
                WxPayParam wxPayParam = getWxPayParam(orderType, payType, orderNoNew, paymentAmount, wxOpenId, "JSAPI", ip, attachMap);
                Map<String, Object> unifiedOrder = weiXinPayService.generateWeChatOrders(wxPayParam);
                resultMap.put("payInfo", unifiedOrder);
                return true;
            }
            //h5
            else if (PayTypeEnum.MWEB.desc().equals(payType)) {
                WxPayParam wxPayParam = getWxPayParam(orderType, payType, orderNo, paymentAmount, wxOpenId, "MWEB", ip, attachMap);
                WxPayMwebOrderResult wxMap = weiXinPayService.h5Pay(wxPayParam);
                String payInfo = JSONObject.toJSONString(wxMap);
                resultMap.put("payInfo", payInfo);
                return true;
            }
            //钱包支付
            else if (PayTypeEnum.WALLET.desc().equals(payType)) {
                if(!Objects.equals(PayAttach.ORDER_PAY.desc(),orderType)){
                    throw new ServiceException("订单类型非法");
                }
                OrderHead orderHead = orderHeadService.getOne(new QueryWrapper<OrderHead>()
                        .eq(OrderHead.ORDER_NO, orderNo).last("limit 1"));
                if (Objects.isNull(orderHead)) {
                    throw new ServiceException("订单不存在");
                }
                Integer cardType = VipCardTypeEnum.getCardTypeByOrderVipFlagValueThrowE(orderHead.getVipFlag());
                payService.walletPay(orderNo, payPassword, userId, paymentAmount, cardType);
                resultMap.put("wallet", true);
                return true;
            }
        } catch (ServiceException e) {
            throw new ServiceException(e.getMessage());
        } catch (Exception e) {
            log.info("支付异常{}", Arrays.toString(e.getStackTrace()));
            throw new ServiceException("支付异常");
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    public void walletPay(String orderNo, String payPassword, Integer userId, Integer snapshotTotalFee, Integer cardType) {
        //钱包付款
        Boolean b = userMemberCardService.cardPay(userId, payPassword, snapshotTotalFee, orderNo, cardType);
        if (!b) {
            throw new ServiceException("钱包扣款失败");
        }
        orderPayRecordService.payCallBackT(orderNo, PayTypeEnum.WALLET, true);
    }

    //生成微信支付参数
    private WxPayParam getWxPayParam(String ordreType, String payType, String orderNo, Integer snapshotTotalFee, String wxOpenId, String tradeType, String ip, HashMap<String, String> attachMap) {
        return new WxPayParam(ordreType, payType, wxOpenId, snapshotTotalFee, orderNo, ip, wxProperties.getNewNotifyUrl(), tradeType, JSONUtil.toJsonStr(attachMap));
    }

}
